/**
 * （1）ES6 Set + 扩展运算符
 * （2）ES6 Set + Array.from
 * （3）filter + indexOf
 * （4）filter + includes + 新数组
 * （5）reduce方法
 * （6）Map数据结构
 * （7）双重for循环
 * （8）sort + 相邻比较
 * （9）对象属性去重法
 * （10）hasOwnProperty方法
 * （11）根据对象属性去重
 * （12）根据多个属性去重
 * （13）JSON.stringify去重对象
 * （14）Map存储完整对象去重
 */
// 测试数据
const testArray = [1, 2, 2, 3, 4, 4, 5, 'a', 'a', 'b', null, null, undefined, undefined, NaN, NaN, {}, {}];
const numberArray = [1, 2, 2, 3, 4, 4, 5, 1, 3, 6, 7, 7, 8];
const stringArray = ['apple', 'banana', 'apple', 'orange', 'banana', 'grape'];

console.log("原始测试数组:", testArray);
console.log("数字数组:", numberArray);
console.log("字符串数组:", stringArray);
console.log("\n" + "=".repeat(50) + "\n");

// ===== 方法1: ES6 Set + 扩展运算符 =====
console.log("=== 方法1: ES6 Set + 扩展运算符 ===");
function uniqueBySet(arr) {
    return [...new Set(arr)];
}
console.log("结果:", uniqueBySet(testArray));
console.log("注意: NaN会被正确去重，但{}对象不会");

// ===== 方法2: ES6 Set + Array.from =====
console.log("\n=== 方法2: ES6 Set + Array.from ===");
function uniqueByArrayFrom(arr) {
    return Array.from(new Set(arr));
}
console.log("结果:", uniqueByArrayFrom(testArray));

// ===== 方法3: filter + indexOf =====
console.log("\n=== 方法3: filter + indexOf ===");
function uniqueByIndexOf(arr) {
    return arr.filter((item, index) => arr.indexOf(item) === index);
}
console.log("结果:", uniqueByIndexOf(testArray));
console.log("注意: NaN会被过滤掉，因为indexOf找不到NaN");

// ===== 方法4: filter + includes + 新数组 =====
console.log("\n=== 方法4: filter + includes + 新数组 ===");
function uniqueByIncludes(arr) {
    const result = [];
    arr.forEach(item => {
        if (!result.includes(item)) {
            result.push(item);
        }
    });
    return result;
}
console.log("结果:", uniqueByIncludes(testArray));
console.log("注意: NaN不会被正确处理");

// ===== 方法5: reduce方法 =====
console.log("\n=== 方法5: reduce方法 ===");
function uniqueByReduce(arr) {
    return arr.reduce((acc, current) => {
        if (!acc.includes(current)) {
            acc.push(current);
        }
        return acc;
    }, []);
}
console.log("结果:", uniqueByReduce(numberArray));

// ===== 方法6: Map数据结构 =====
console.log("\n=== 方法6: Map数据结构 ===");
function uniqueByMap(arr) {
    const map = new Map();
    const result = [];
    arr.forEach(item => {
        if (!map.has(item)) {
            map.set(item, true);
            result.push(item);
        }
    });
    return result;
}
console.log("结果:", uniqueByMap(testArray));
console.log("注意: 能正确处理NaN，但不能处理对象");

// ===== 方法7: 双重for循环 =====
console.log("\n=== 方法7: 双重for循环 ===");
function uniqueByDoubleFor(arr) {
    const result = [];
    for (let i = 0; i < arr.length; i++) {
        let isDuplicate = false;
        for (let j = 0; j < result.length; j++) {
            if (arr[i] === result[j]) {
                isDuplicate = true;
                break;
            }
        }
        if (!isDuplicate) {
            result.push(arr[i]);
        }
    }
    return result;
}
console.log("结果:", uniqueByDoubleFor(numberArray));

// ===== 方法8: sort + 相邻比较 =====
console.log("\n=== 方法8: sort + 相邻比较 ===");
function uniqueBySort(arr) {
    const sorted = [...arr].sort();
    const result = [sorted[0]];
    for (let i = 1; i < sorted.length; i++) {
        if (sorted[i] !== sorted[i - 1]) {
            result.push(sorted[i]);
        }
    }
    return result;
}
console.log("结果:", uniqueBySort(numberArray));
console.log("注意: 会改变原数组顺序，且对混合类型数组效果不佳");

// ===== 方法9: 对象属性去重法 =====
console.log("\n=== 方法9: 对象属性去重法 ===");
function uniqueByObject(arr) {
    const obj = {};
    const result = [];
    arr.forEach(item => {
        const key = typeof item + item; // 类型 + 值作为key
        if (!obj[key]) {
            obj[key] = true;
            result.push(item);
        }
    });
    return result;
}
console.log("结果:", uniqueByObject(numberArray));

// ===== 方法10: hasOwnProperty方法 =====
console.log("\n=== 方法10: hasOwnProperty方法 ===");
function uniqueByHasOwnProperty(arr) {
    const obj = {};
    return arr.filter(item => {
        const key = typeof item + JSON.stringify(item);
        return obj.hasOwnProperty(key) ? false : (obj[key] = true);
    });
}
console.log("结果:", uniqueByHasOwnProperty(stringArray));

// ===== 针对对象数组的去重方法 =====
console.log("\n=== 对象数组去重方法 ===");

const objArray = [
    {id: 1, name: 'Alice'},
    {id: 2, name: 'Bob'},
    {id: 1, name: 'Alice'},
    {id: 3, name: 'Charlie'},
    {id: 2, name: 'Bob'}
];

console.log("原始对象数组:", objArray);

// 方法11: 根据对象的某个属性去重
console.log("\n=== 方法11: 根据对象属性去重 ===");
function uniqueByProperty(arr, property) {
    const seen = new Set();
    return arr.filter(item => {
        const value = item[property];
        if (seen.has(value)) {
            return false;
        }
        seen.add(value);
        return true;
    });
}
console.log("根据id去重:", uniqueByProperty(objArray, 'id'));

// 方法12: 根据对象的多个属性去重
console.log("\n=== 方法12: 根据多个属性去重 ===");
function uniqueByMultipleProperties(arr, properties) {
    const seen = new Set();
    return arr.filter(item => {
        const key = properties.map(prop => item[prop]).join('|');
        if (seen.has(key)) {
            return false;
        }
        seen.add(key);
        return true;
    });
}
console.log("根据id和name去重:", uniqueByMultipleProperties(objArray, ['id', 'name']));

// 方法13: JSON.stringify去重对象
console.log("\n=== 方法13: JSON.stringify去重对象 ===");
function uniqueByJSON(arr) {
    const seen = new Set();
    return arr.filter(item => {
        const serialized = JSON.stringify(item);
        if (seen.has(serialized)) {
            return false;
        }
        seen.add(serialized);
        return true;
    });
}
console.log("JSON去重结果:", uniqueByJSON(objArray));

// 方法14: Map存储完整对象去重
console.log("\n=== 方法14: Map存储完整对象去重 ===");
function uniqueByMapObject(arr, keyFunc) {
    const map = new Map();
    arr.forEach(item => {
        const key = keyFunc ? keyFunc(item) : JSON.stringify(item);
        if (!map.has(key)) {
            map.set(key, item);
        }
    });
    return Array.from(map.values());
}
console.log("Map对象去重:", uniqueByMapObject(objArray, item => item.id));

// 方法15: 自定义比较函数去重
console.log("\n=== 方法15: 自定义比较函数去重 ===");
function uniqueByComparator(arr, compareFn) {
    return arr.filter((item, index) => {
        return !arr.slice(0, index).some(prevItem => compareFn(item, prevItem));
    });
}

const customCompare = (a, b) => a.id === b.id && a.name === b.name;
console.log("自定义比较去重:", uniqueByComparator(objArray, customCompare));

// ===== 性能测试 =====
console.log("\n=== 性能测试 ===");

// 创建大数组进行性能测试
const largeArray = Array.from({length: 10000}, () => Math.floor(Math.random() * 1000));

console.log("测试数组长度:", largeArray.length);

function performanceTest(func, name, arr) {
    const start = performance.now();
    const result = func(arr);
    const end = performance.now();
    console.log(`${name}: ${(end - start).toFixed(2)}ms, 结果长度: ${result.length}`);
}

performanceTest(uniqueBySet, "Set方法", largeArray);
performanceTest(uniqueByIndexOf, "indexOf方法", largeArray);
performanceTest(uniqueByMap, "Map方法", largeArray);
performanceTest(uniqueByReduce, "reduce方法", largeArray);

// ===== 特殊情况处理 =====
console.log("\n=== 特殊情况处理 ===");

// NaN处理
const nanArray = [1, NaN, 2, NaN, 3];
console.log("包含NaN的数组:", nanArray);
console.log("Set方法处理NaN:", uniqueBySet(nanArray));

// 处理null和undefined
const nullArray = [1, null, 2, undefined, null, undefined, 3];
console.log("包含null/undefined:", nullArray);
console.log("Set方法处理:", uniqueBySet(nullArray));

// 处理不同类型的相同值
const mixedArray = [1, '1', true, 'true', 0, false, '', null, undefined];
console.log("混合类型数组:", mixedArray);
console.log("Set方法处理:", uniqueBySet(mixedArray));

console.log("\n=== 总结 ===");
console.log(`
数组去重方法选择建议：

1. 简单数组(数字、字符串): 使用 [...new Set(arr)]
2. 需要考虑NaN: 使用Set或Map方法
3. 对象数组: 根据属性去重，使用Map或自定义比较函数
4. 性能要求高: Set > Map > indexOf > includes
5. 兼容性要求: filter + indexOf
6. 复杂比较逻辑: 自定义比较函数

注意事项：
- Set能正确处理NaN，但不能处理对象引用
- indexOf不能正确处理NaN
- 对象数组需要根据具体属性或序列化后比较
- 性能：Set方法通常最快，双重循环最慢
`); 